/* global window */
/* global document */
/* global location */
/* eslint no-restricted-globals: ["error", "event"] */

import {routerRedux} from 'dva/router'
import {parse} from 'qs'
import config from 'config'
import {queryArray} from 'utils'
import {setToken} from 'utils/authority'
import {EnumRoleType} from 'enums'
import {logout, query} from 'services/app'
import * as menusService from 'services/menus'
import queryString from 'query-string'

const {prefix} = config

export default {
  namespace: 'app',
  state: {
    panes: [],
    activeKey: "",
    user: {},
    permissions: {
      visit: [],
    },
    menu: [
      {
        id: 1,
        icon: 'laptop',
        name: 'Dashboard',
        route: '/dashboard',
      },
    ],
    destroyed: false,
    menuPopoverVisible: false,
    siderFold: window.localStorage.getItem(`${prefix}siderFold`) === 'true',
    darkTheme: window.localStorage.getItem(`${prefix}darkTheme`) === undefined ? true : (window.localStorage.getItem(`${prefix}darkTheme`) === 'true'),
    isNavbar: document.body.clientWidth < 769,
    navOpenKeys: JSON.parse(window.localStorage.getItem(`${prefix}navOpenKeys`)) || [],
    locationPathname: '',
    locationQuery: {},
  },
  subscriptions: {
    setupHistory ({dispatch, history}) {
      history.listen((location) => {
        dispatch({
          type: 'updateState',
          payload: {
            locationPathname: location.pathname,
            locationQuery: location.query,
          },
        })
      })
    },

    setup ({dispatch, history}) {
      if (history.location.pathname !== '/login') {
        dispatch({type: 'query'})
      }
      let tid
      window.onresize = () => {
        clearTimeout(tid)
        tid = setTimeout(() => {
          dispatch({type: 'changeNavbar'})
        }, 300)
      }
    },

  },
  effects: {

    * query ({
               payload,
             }, {call, put, select}) {
      const {code, data: user} = yield call(query, payload)
      const {locationPathname} = yield select(_ => _.app)
      if (code === 0 && user) {
        const {data: list} = yield call(menusService.query)
        const {permissions} = user
        let menu = list
        if (permissions.role === EnumRoleType.ADMIN || permissions.role === EnumRoleType.DEVELOPER) {
          permissions.visit = list.map(item => item.id)
        } else {
          menu = list.filter((item) => {
            const cases = [
              permissions.visit.includes(item.id),
              // item.mpid ? permissions.visit.includes(item.mpid) || item.mpid === '-1' : true,
              // item.bpid ? permissions.visit.includes(item.bpid) : true,
            ]
            return cases.every(_ => _)
          })
        }

        let m = queryArray(menu, locationPathname, 'route')

        if (!m) {
          m = {}
          let tmp = menu.filter(_ => {
            if (_.route) {
              return true
            }
          })
          if (tmp && tmp.length > 0) {
            m = tmp[0]
          }
        }

        const panes = [{
          title: m.name,
          key: m.route,
        }]

        yield put({
          type: 'updateState',
          payload: {
            user,
            permissions,
            menu,
            panes,
            activeKey: m.route,
          },
        })
        if (m.route || location.pathname === '/login') {
          yield put(routerRedux.push({
            pathname: m.route || '/dashboard',
          }))
        }
      } else if (config.openPages && config.openPages.indexOf(locationPathname) < 0) {
        yield put(routerRedux.push({
          pathname: '/login',
          search: queryString.stringify({
            from: locationPathname,
          }),
        }))
      }
    },

    * logout ({payload}, {call, put, select}) {
      const data = yield call(logout, parse(payload))
      const {locationPathname} = yield select(_ => _.app)
      if (data.success) {
        setToken('')

        yield put({
          type: 'updateState', payload: {
            user: {},
            permissions: {visit: []},
            menu: [{
              id: 1,
              icon: 'laptop',
              name: 'Dashboard',
              route: '/dashboard',
            }],
            panes: [],
            activeKey: "",
          },
        })
        // yield put({type: 'query'})
        yield put(routerRedux.push({
          pathname: '/login',
          search: queryString.stringify({
            from: locationPathname,
          }),
        }))
      } else {
        throw (data)
      }
    },

    * changeNavbar (action, {put, select}) {
      const {app} = yield (select(_ => _))
      const isNavbar = document.body.clientWidth < 769
      if (isNavbar !== app.isNavbar) {
        yield put({type: 'handleNavbar', payload: isNavbar})
      }
    },

  },
  reducers: {
    updateState (state, {payload}) {
      return {
        ...state,
        ...payload,
      }
    },

    destroy (state) {
      return {
        ...state,
        user: {},
        permissions: {visit: []},
        menu: [{
          id: 1,
          icon: 'laptop',
          title: '首页总览',
          key: '/dashboard',
        }],
        panes: [],
        activeKey: "",
        destroyed: true,
      }
    },

    closeOtherTab (state) {
      const {panes, activeKey} = state
      const pane = queryArray(panes, activeKey)

      return {
        ...state,
        panes: [pane],
      }
    },

    closeAllTab (state) {
      return {
        ...state,
        panes: [{
          id: 1,
          icon: 'laptop',
          title: '首页总览',
          key: '/dashboard',
        }],
        activeKey: '/dashboard',
      }
    },

    changeTab (state, {payload}) {
      const {key, changed, children} = payload
      if (window.clossetab === key) {
        window.clossetab = undefined
        return {
          ...state,
        }
      }

      const {panes} = state

      if (changed) {
        const pane = queryArray(panes, key)
        if (pane) {
          pane.content = children
        }
      }

      return {
        ...state,
        activeKey: key,
      }
    },

    addTab (state, {payload}) {
      const {activeKey, panes} = state
      const {menu, children} = payload
      const {name, route} = menu
      let exists = false

      if (activeKey === route) {
        return {
          ...state,
        }
      }

      if (window.clossetab === route) {
        window.clossetab = undefined
      }

      for (let i = 0; i < panes.length; i++) {
        let pane = panes[i]
        if (pane.key === route) {
          exists = true
          if (children !== pane.content) {
            pane.content = children
          }
          return {
            ...state,
            activeKey: route,
          }
        }
      }

      if (!exists) {
        routerRedux.push(route)
        return {
          ...state,
          panes: panes.concat([{title: name, key: route, content: children}]),
          activeKey: route,
        }
      }
    },

    closeTab (state, {payload}) {
      const {panes, activeKey} = state
      const {key} = payload
      let newKey = activeKey

      const delItem = queryArray(panes, key)
      const delIdx = panes.indexOf(delItem)
      let tmpPanes = panes.filter(_ => _.key !== key)
      if (activeKey === key) {
        const lastIdx = panes.length - 1
        const idx = delIdx === lastIdx ? lastIdx - 1 : delIdx
        newKey = tmpPanes[idx].key
      }

      return {
        ...state,
        panes: tmpPanes,
        activeKey: newKey,
      }
    },

    switchSider (state) {
      window.localStorage.setItem(`${prefix}siderFold`, !state.siderFold)
      return {
        ...state,
        siderFold: !state.siderFold,
      }
    },

    switchTheme (state) {
      window.localStorage.setItem(`${prefix}darkTheme`, !state.darkTheme)
      return {
        ...state,
        darkTheme: !state.darkTheme,
      }
    },

    switchMenuPopver (state) {
      return {
        ...state,
        menuPopoverVisible: !state.menuPopoverVisible,
      }
    },

    handleNavbar (state, {payload}) {
      return {
        ...state,
        isNavbar: payload,
      }
    },

    handleNavOpenKeys (state, {payload: navOpenKeys}) {
      return {
        ...state,
        ...navOpenKeys,
      }
    },
  },
}
